/**
 * 
 */
package de.unibi.techfak.msp.eatThis.manager;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import de.unibi.techfak.msp.eatThis.bean.FoodBean;
import de.unibi.techfak.msp.eatThis.manager.exception.EntityException;
import de.unibi.techfak.msp.eatThis.manager.exception.EntityNotFoundException;
import de.unibi.techfak.msp.eatThis.messages.Messages;

/**
 * FoodManager stellt die Verbindung zur Datenbank via JDBC über
 * {@link GenericManager} her. Dieser Manager füllt dann eine FoodBean, die alle
 * wichtigen Felder des Lebensmittels enthält.
 * 
 * @author Michael Adams
 * 
 */
public class FoodManager extends GenericManager<FoodBean> {

    /** ResultSet zum Ausführen der SQL Befehle. */
    private ResultSet rs = null;
    /** Prepared Statement um SQL Zugriff sicher zu machen. */
    private PreparedStatement ps = null;

    private static final String CREATE_FIELDS = "name, foodGroup, ingredients, ean ";

    private static final String SELECT_FIELDS = "idFood, " + CREATE_FIELDS;

    /**
     * Sucht einen Eintrag in der Datenbank anhand des Namens.
     * 
     * @param name
     *            ist der Name des Produktes.
     * @return die gefüllte Bean.
     * @throws EntityException
     *             ex, falls kein Eintrag existiert.
     */
    public final FoodBean getByName(final String name) throws EntityException {
        checkArguments(name);
        return getByString("name", name);
    }

    /**
     * Sucht einen Eintrag in der Datenbank anhand des Namens.
     * 
     * @param ean
     *            ist die EAN des Produktes.
     * @return die gefüllte Bean.
     * @throws EntityException
     *             ex, falls kein Eintrag existiert.
     */
    public final FoodBean getByEAN(final String ean) throws EntityException {
        checkArguments(ean);
        return getByString("ean", ean);
    }

    @Deprecated
    @Override
    final Integer update(final FoodBean bean) throws EntityException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public final Integer create(final FoodBean bean) {
        Connection con = openConnection();

        try {
            ps = con.prepareStatement("INSERT INTO Food (" + CREATE_FIELDS
                    + ") VALUES (?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);

            ps.setString(1, bean.getName());
            ps.setString(2, bean.getGroup());
            ps.setString(3, bean.getIngredients());
            ps.setString(4, bean.getEan());

            return executeCreatePs(ps);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        } finally {
            closeConnection(con);
        }
    }

    @Override
    final FoodBean get(final Integer beanId) throws EntityException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    void delete(final Integer beanId) throws EntityException {
        // TODO Auto-generated method stub

    }

    /**
     * @param rs
     *            ist ein übergebenes ResultSet
     * @return UserBean ist eine aus dem Resultset extrahierte UserBean.
     * @throws SQLException
     *             ex
     */
    private FoodBean extractFoodBean(final ResultSet rs) throws SQLException {
        FoodBean fb = new FoodBean(null);

        fb.setId(rs.getInt("idFood"));
        fb.setName(rs.getString("name"));
        fb.setGroup(rs.getString("foodGroup"));
        fb.setIngredients(rs.getString("ingredients"));
        fb.setEan(rs.getString("ean"));

        return fb;
    }

    /**
     * Holt eine FoodBean mittels String aus der Datenbank ab.
     * 
     * @param where
     *            ist das where statement
     * @param value
     *            der dazugehörige Wert
     * @return FoodBean ist die extrahierte Bean.
     * @throws EntityException
     *             ex.
     */
    private FoodBean getByString(final String where, final String value)
            throws EntityException {

        Connection con = openConnection();

        try {
            checkArguments(value);
            ps = con.prepareStatement("SELECT " + SELECT_FIELDS
                    + "FROM Food WHERE " + where + " = ?");
            ps.setString(1, value);

            rs = ps.executeQuery();

            if (!rs.first()) {
                throw new EntityNotFoundException(String.format(
                        Messages.EXCEPTION_ATTRIBUTE_NOT_FOUND, "Lebensmittel",
                        where, value));
            }
            return extractFoodBean(rs);
        } catch (SQLException sqlEx) {
            throw new EntityNotFoundException(sqlEx);
        } finally {
            closeConnection(con);
        }

    }

    /**
     * Holt die Liste ab!
     * 
     * @throws EntityNotFoundException
     *             ex
     * @throws SQLException
     *             ex
     */
    public List<FoodBean> getFoodList() throws EntityException {

        Connection con = openConnection();
        List<FoodBean> foodList = new ArrayList<FoodBean>();

        try {
            ps = con.prepareStatement("SELECT " + SELECT_FIELDS + "FROM Food");
            rs = ps.executeQuery();

            while (rs.next()) {
                foodList.add(extractFoodBean(rs));
            }

            return foodList;

        } catch (SQLException sqlEx) {
            throw new EntityNotFoundException(sqlEx);
        } finally {
            closeConnection(con);

        }

    }

}
